﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using OpenLS.Media;
using OpenLS.Spreadsheet.UI.Internals;
using OpenLS.Spreadsheet.UI.Internals.Resources;

namespace OpenLS.Spreadsheet.UI
{
    
    internal class ColumnsControl : DimensionsControl
    {
        static ColumnsControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColumnsControl), new FrameworkPropertyMetadata(typeof(ColumnsControl)));
        }
        protected override Size MeasureOverride(Size constraint)
        {
            var columns = Columns;
            if (columns == null)
                return new Size();
            FormattedText text = new FormattedText("ABCDE123", CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, GetTypeFace(),FontSize, Brushes.Black);
            return new Size(Enumerable.Sum(columns, c => c.ActualWidth), text.Height + 6); // 6 == margin*2
        }


        protected override void DragDimension(Dimension borderDimension, Vector vector)
        {
            Column column = (Column) borderDimension;
            column.Width = column.ActualWidth + vector.X;

        }

        protected override void OnMouseDimension(Dimension dimension)
        {

            Column column1 = (Column) dimension;
            Contract.Assert(column1 != null);
            var activeCell = SpreadsheetElement.GetWorkingActiveCell(this);
            int offset = column1.Worksheet.Columns.GetIndexForOffset(/*column1.Offset + */Mouse.GetPosition(Mouse.Captured).X + this.Fragment.Worksheet.Columns[Fragment.Left].Offset);
            offset = Math.Max(offset, 0);
            Column column2 = column1.Worksheet.Columns[offset];
            var oldValue = SpreadsheetElement.GetWorkingSelection(this);
            if (oldValue is CompositeRange)
            {
                //\\                column2.Worksheet.Selection = CompositeRange.CreateWithLast((CompositeRange) column2.Worksheet.Selection,  new FullColumnRange(column1, column2));
                SpreadsheetElement.SetCurrentRangeForRoot(this, CompositeRange.CreateWithLast((CompositeRange)oldValue,
                    new FullColumnRange(column1, column2)), activeCell);
            }
            else
            {
                
                SpreadsheetElement.SetCurrentRangeForRoot(this, new FullColumnRange(column1, column2), activeCell);
                column1.Worksheet.GetPaneFor(column1.Worksheet[0, column2.Index]).EnsureVisible(new CellAddress(0, column2.Index));

            }
            //column2.Worksheet.Selection = new FullColumnRange(column1, column2);

        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            if (IsEmpty)
                return;
            Point position = e.MouseDevice.GetPosition(this);
            var hit = GetHit(position);
            if (hit == null)
                return;
            Column d = (Column) hit.BorderDimesion;
            if (d != null)
            {
                using (d.Worksheet.Workbook.CreateUndoScope(UIStringTable.AutoFitColumnWidth))
                {
                    foreach (var column in getColumns(d))
                        column.AutoFit();
                }

            }
        }
        static IEnumerable<Column> getColumns(Column column)
        {
            var columnRange = column.Worksheet.Selection as FullColumnRange;
            if (columnRange != null && columnRange.Contains(column))
            {
                foreach (var column2 in columnRange.GetColumns())
                {
                    yield return column2;
                }
            }
            else
                yield return column;
        }



        protected override Rect GetRect(Dimension dimension)
        {
            Column c = (Column) dimension;
            return new Rect(new Point(c.Offset - c.Worksheet.Columns [this.Fragment.Left].Offset, 0), new Size(c.ActualWidth, this.ActualHeight));
        }

        protected override DimensionHit GetHit(Point position)
        {
            Dimension d = GetItemAt(position);
            if (d == null)
                return null;
            Rect rect = GetRect(d);
            if (position.X >= rect.Right - tolerance)
            {
                return new DimensionHit(null, d);
            }
            if (position.X <= rect.Left + tolerance)
            {
                if (d.Index == 0)
                    return new DimensionHit(d, null);
                d = d.Worksheet.Columns[d.Index - 1];
                return new DimensionHit(null, d);
            }
            return new DimensionHit(d, null);

        }

        protected override void FinishDragDimension(Dimension borderDimension)
        {
            Column c = (Column) borderDimension;
            if (!borderDimension.Worksheet.Selection.ContainsColumn(c))
                return;
            borderDimension.Worksheet.Selection.SetColumnsWidth(c.ActualWidth);
        }

        protected override void SelectDimension(Dimension d, MouseButton argsChangedButton)
        {
            var column = (Column)d;
            var mergeType = GetMergeType();
            var activeCell = SpreadsheetElement.GetWorkingActiveCell(this);
            switch (mergeType)
            {
                case MergeType.Extend:
                    {
                        var range = RangeExtensions.MergeColumn(
                            SpreadsheetElement.GetWorkingSelection(this), column, mergeType);
                        SpreadsheetElement.SetCurrentRangeForRoot(this, range, range.FirstCell);
                        /* column.Worksheet.Selection = RangeExtensions.MergeColumn(column.Worksheet.Selection, column,
                          /                                                        mergeType);
                         */
                        //\\);
                        return;
                    }
                case MergeType.Union:
                    {
                        var range = RangeExtensions.MergeColumn(
                            SpreadsheetElement.GetWorkingSelection(this),
                            column, mergeType);
                        SpreadsheetElement.SetCurrentRangeForRoot(this,
                                                                  range, range.FirstCell);
                        //\\                                                                             mergeType));
                        //\\                        column.Worksheet.Selection = RangeExtensions.MergeColumn(column.Worksheet.Selection, column,
                        //\\                                                                             mergeType);
                        CaptureDimension(d);
                        return;
                    }
            }
            {
                bool reselect = argsChangedButton != MouseButton.Right;
                if (!reselect)
                {
                    var rr = column.Worksheet.Selection as FullColumnRange;
                    if (rr == null)
                        reselect = true;
                    else
                        reselect = !rr.Contains(column);
                }
                if (reselect)
                {
                    EditedCell c = EditionElement.GetEditedCell(this);//\\
                    if (c != null && c.AcceptsPoint)
                    {
                        if (argsChangedButton == MouseButton.Right)
                            return;
                        c._wantsCapture = true;
                        c.Formula.ActivateColumnReference(column);
                        return;

                    }
                    SpreadsheetElement.SetCurrentRangeForRoot(this, new FullColumnRange(column), column[0]);
                    //column.Worksheet.Selection = new FullColumnRange(column);
                }
                CaptureDimension(d);
            }

        }

        protected override void OnQueryCursor(QueryCursorEventArgs e)
        {
            if (IsEmpty)
                return;
            Point position = e.MouseDevice.GetPosition(this);
            var hit = GetHit(position);
            if (hit == null)
                return;

            if (hit.Dimension != null)
                e.Cursor = OfficeCursors.ArrowDown;
            else
            {
                e.Cursor = OfficeCursors.SizeWE;
            }
        }
        

        IEnumerable<Column> Columns
        {get
            { return this.ItemsSource as IEnumerable<Column>; }
        }
    }
}
